package org.dromara.web.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.StrUtil;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.profile.Language;
import com.tencentcloudapi.trtc.v20190722.TrtcClient;
import com.tencentcloudapi.trtc.v20190722.models.AgentParams;
import com.tencentcloudapi.trtc.v20190722.models.AudioEncode;
import com.tencentcloudapi.trtc.v20190722.models.CloudVod;
import com.tencentcloudapi.trtc.v20190722.models.CreateCloudRecordingRequest;
import com.tencentcloudapi.trtc.v20190722.models.CreateCloudRecordingResponse;
import com.tencentcloudapi.trtc.v20190722.models.DeleteCloudRecordingRequest;
import com.tencentcloudapi.trtc.v20190722.models.DeleteCloudRecordingResponse;
import com.tencentcloudapi.trtc.v20190722.models.McuAudioParams;
import com.tencentcloudapi.trtc.v20190722.models.McuCloudVod;
import com.tencentcloudapi.trtc.v20190722.models.McuLayoutParams;
import com.tencentcloudapi.trtc.v20190722.models.McuPublishCdnParam;
import com.tencentcloudapi.trtc.v20190722.models.McuRecordParams;
import com.tencentcloudapi.trtc.v20190722.models.McuStorageParams;
import com.tencentcloudapi.trtc.v20190722.models.McuTencentVod;
import com.tencentcloudapi.trtc.v20190722.models.McuVideoParams;
import com.tencentcloudapi.trtc.v20190722.models.MixLayoutParams;
import com.tencentcloudapi.trtc.v20190722.models.MixTranscodeParams;
import com.tencentcloudapi.trtc.v20190722.models.RecordParams;
import com.tencentcloudapi.trtc.v20190722.models.StartPublishCdnStreamRequest;
import com.tencentcloudapi.trtc.v20190722.models.StartPublishCdnStreamResponse;
import com.tencentcloudapi.trtc.v20190722.models.StopPublishCdnStreamRequest;
import com.tencentcloudapi.trtc.v20190722.models.StopPublishCdnStreamResponse;
import com.tencentcloudapi.trtc.v20190722.models.StorageParams;
import com.tencentcloudapi.trtc.v20190722.models.TencentVod;
import com.tencentcloudapi.trtc.v20190722.models.VideoEncode;
import com.tencentcloudapi.trtc.v20190722.models.VideoParams;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.MediaInfo;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaResponse;
import com.tencentyun.TLSSigAPIv2;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.tenant.properties.TenantProperties;
import org.dromara.system.domain.bo.TrtcRecordTaskBo;
import org.dromara.system.domain.vo.TrtcRecordTaskVo;
import org.dromara.system.service.ITrtcRecordTaskService;
import org.dromara.web.properties.TrtcProperties;
import org.dromara.web.utils.TrtcPushUrlGenerator;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;

/**
 * TRTC 房间回调控制器
 *
 * @author aaron
 */
@Slf4j
@SaIgnore
@RestController
@RequiredArgsConstructor
@RequestMapping("/trtc/callback")
public class TrtcCallbackController {
    private final TrtcProperties trtcProperties;
    private final ITrtcRecordTaskService trtcRecordTaskService;

    /**
     * 处理房间事件回调
     *
     * @param body 回调数据
     * @return 处理结果
     */
    @PostMapping("/room")
    public R<Void> handleRoomCallback(@RequestBody String body) {
        log.info("收到TRTC房间回调: {}", body);

        try {
            Map<String, Object> callbackData = JsonUtils.parseMap(body);

            // 打印回调数据的所有字段
            log.info("=== TRTC回调数据开始 ===");
            for (Map.Entry<String, Object> entry : callbackData.entrySet()) {
                if (entry.getValue() instanceof Map) {
                    log.info("字段名: {}, 值类型: Map", entry.getKey());
                    Map<String, Object> nestedMap = (Map<String, Object>) entry.getValue();
                    for (Map.Entry<String, Object> nestedEntry : nestedMap.entrySet()) {
                        log.info("  - 子字段名: {}, 子字段值: {}, 子字段类型: {}",
                            nestedEntry.getKey(),
                            nestedEntry.getValue(),
                            nestedEntry.getValue() != null ? nestedEntry.getValue().getClass().getSimpleName() : "null");
                    }
                } else {
                    log.info("字段名: {}, 字段值: {}, 值类型: {}",
                        entry.getKey(),
                        entry.getValue(),
                        entry.getValue() != null ? entry.getValue().getClass().getSimpleName() : "null");
                }
            }
            log.info("=== TRTC回调数据结束 ===");

            Integer eventType = (Integer) callbackData.get("EventType");
            Map<String, Object> eventInfo = (Map<String, Object>) callbackData.get("EventInfo");

            switch (eventType) {
                case 101:
                    handleRoomCreated(eventInfo);
                    break;
                case 102:
                    handleRoomDestroyed(eventInfo);
                    break;
                case 103:
                    handleUserEntered(eventInfo);
                    break;
                case 104:
                    handleUserExited(eventInfo);
                    break;
                default:
                    log.warn("未知的TRTC回调事件类型: {}", eventType);
            }

            return R.ok();
        } catch (Exception e) {
            log.error("处理TRTC回调失败", e);
            return R.fail("处理回调失败");
        }
    }

    /**
     * 处理房间创建事件
     */
    private void handleRoomCreated(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        log.info("房间创建: {}", roomId);
        try {
            Credential cred = new Credential(trtcProperties.getSecretId(), trtcProperties.getSecretKey());

            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setReqMethod("GET"); // get请求(默认为post请求)
            httpProfile.setConnTimeout(30); // 请求连接超时时间，单位为秒(默认60秒)
            httpProfile.setWriteTimeout(30);  // 设置写入超时时间，单位为秒(默认0秒)
            httpProfile.setReadTimeout(30);  // 设置读取超时时间，单位为秒(默认0秒)
            httpProfile.setEndpoint(trtcProperties.getEndpoint()); // 指定接入地域域名(默认就近接入)

            // 实例化一个client选项
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setSignMethod(ClientProfile.SIGN_TC3_256); // 指定签名算法(默认为TC3-HMAC-SHA256)
            clientProfile.setHttpProfile(httpProfile);
            clientProfile.setDebug(true);
            clientProfile.setLanguage(Language.ZH_CN);
            // 实例化要请求产品(以cvm为例)的client对象,clientProfile是可选的
            TrtcClient client = new TrtcClient(cred, "ap-shanghai", clientProfile);

            CreateCloudRecordingRequest request = new CreateCloudRecordingRequest();
            String userId = "recorder_" + roomId;
            request.setUserId(userId);
            Long sdkAppId = trtcProperties.getSdkAppId();
            TLSSigAPIv2 api = new TLSSigAPIv2(sdkAppId, trtcProperties.getSdkAppKey());
            String userSig = api.genUserSig(request.getUserId(), 180*86400);
            request.setUserSig(userSig);
            request.setSdkAppId(sdkAppId);
            request.setRoomId(roomId);
            RecordParams recordParams = new RecordParams();
            recordParams.setMaxIdleTime(60L);
            recordParams.setStreamType(0L);
            recordParams.setRecordMode(2L);
            request.setRecordParams(recordParams);
            MixTranscodeParams maxTranscodeParams = new MixTranscodeParams();
            VideoParams videoParams = new VideoParams();
            videoParams.setWidth(360L);
            videoParams.setHeight(640L);
            videoParams.setBitRate(500000L);
            videoParams.setFps(15L);
            videoParams.setGop(10L);
            maxTranscodeParams.setVideoParams(videoParams);
            request.setMixTranscodeParams(maxTranscodeParams);
            MixLayoutParams mixLayoutParams = new MixLayoutParams();
            mixLayoutParams.setMixLayoutMode(3L);
            request.setMixLayoutParams(mixLayoutParams);
            StorageParams storageParams = new StorageParams();
            CloudVod cloudVod = new CloudVod();
            TencentVod tencentVod = new TencentVod();
            tencentVod.setExpireTime(0L);
            cloudVod.setTencentVod(tencentVod);
            storageParams.setCloudVod(cloudVod);
            request.setStorageParams(storageParams);
            request.setRoomIdType(0L);
            StartPublishCdnStreamRequest startPublishCdnStreamRequest = new StartPublishCdnStreamRequest();
            String streamNamePrefix = "tuiroom_";
            String publishCdnUrl = TrtcPushUrlGenerator.generatePushUrl(roomId, streamNamePrefix, trtcProperties.getPushDomain(), trtcProperties.getPushKey());
            String playUrl = TrtcPushUrlGenerator.generatePlayUrl(roomId, streamNamePrefix, trtcProperties.getPlayDomain(), trtcProperties.getPlayKey());
            startPublishCdnStreamRequest.setSdkAppId(sdkAppId);
            startPublishCdnStreamRequest.setRoomId(roomId);
            startPublishCdnStreamRequest.setRoomIdType(1L);
            AgentParams agentParams = new AgentParams();
            agentParams.setUserId(userId);
            agentParams.setUserSig(userSig);
            startPublishCdnStreamRequest.setAgentParams(agentParams);
            startPublishCdnStreamRequest.setWithTranscoding(1L);
            McuAudioParams mcuAudioParams = new McuAudioParams();
            AudioEncode audioEncode = new AudioEncode();
            audioEncode.setSampleRate(48000L);
            audioEncode.setBitRate(64L);
            audioEncode.setChannel(2L);
            mcuAudioParams.setAudioEncode(audioEncode);
            startPublishCdnStreamRequest.setAudioParams(mcuAudioParams);
            McuVideoParams mcuVideoParams = new McuVideoParams();
            VideoEncode videoEncode = new VideoEncode();
            videoEncode.setWidth(1280L);
            videoEncode.setHeight(720L);
            videoEncode.setFps(15L);
            videoEncode.setBitRate(512L);
            videoEncode.setGop(2L);
            mcuVideoParams.setVideoEncode(videoEncode);
            mcuVideoParams.setBackGroundColor("0xFF0000");
            McuLayoutParams mcuLayoutParams = new McuLayoutParams();
            mcuLayoutParams.setPureAudioHoldPlaceMode(0L);
            mcuLayoutParams.setMixLayoutMode(1L);
            mcuVideoParams.setLayoutParams(mcuLayoutParams);
            startPublishCdnStreamRequest.setVideoParams(mcuVideoParams);
            McuRecordParams mcuRecordParams = new McuRecordParams();
            mcuRecordParams.setUniRecord(3L);
            mcuRecordParams.setStreamType(0L);
            McuStorageParams mcuStorageParams = new McuStorageParams();
            McuCloudVod mcuCloudVod = new McuCloudVod();
            McuTencentVod mcuTencentVod = new McuTencentVod();
            mcuTencentVod.setExpireTime(86400L);
            mcuCloudVod.setMcuTencentVod(mcuTencentVod);
            mcuStorageParams.setMcuCloudVod(mcuCloudVod);
            mcuRecordParams.setMcuStorageParams(mcuStorageParams);
            startPublishCdnStreamRequest.setRecordParams(mcuRecordParams);
            McuPublishCdnParam[] mcuPublishCdnParams = new McuPublishCdnParam[1];
            mcuPublishCdnParams[0] = new McuPublishCdnParam();
            mcuPublishCdnParams[0].setIsTencentCdn(1L);
            mcuPublishCdnParams[0].setPublishCdnUrl(publishCdnUrl);
            startPublishCdnStreamRequest.setPublishCdnParams(mcuPublishCdnParams);
            StartPublishCdnStreamResponse response = client.StartPublishCdnStream(startPublishCdnStreamRequest);
            String taskId = response.getTaskId();
            String requestId = response.getRequestId();
            TrtcRecordTaskBo trtcRecordTask = new TrtcRecordTaskBo();
            trtcRecordTask.setRoomId(roomId);
            trtcRecordTask.setTaskId(taskId);
            trtcRecordTask.setUserId(userId);
            trtcRecordTask.setRequestId(requestId);
            trtcRecordTask.setSdkAppId(sdkAppId);
            trtcRecordTask.setRecordStartTime(new Date());
            trtcRecordTask.setPublishCdnUrl(publishCdnUrl);
            trtcRecordTask.setPlayUrl(playUrl);
            trtcRecordTaskService.insertByBo(trtcRecordTask);
            System.out.println(response.toString());
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理房间创建事件
     */
    private void handleRoomCreated1(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        log.info("房间创建: {}", roomId);
        try {
            Credential cred = new Credential(trtcProperties.getSecretId(), trtcProperties.getSecretKey());

            // 实例化一个http选项
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setReqMethod("GET"); // get请求(默认为post请求)
            httpProfile.setConnTimeout(30); // 请求连接超时时间，单位为秒(默认60秒)
            httpProfile.setWriteTimeout(30);  // 设置写入超时时间，单位为秒(默认0秒)
            httpProfile.setReadTimeout(30);  // 设置读取超时时间，单位为秒(默认0秒)
            httpProfile.setEndpoint(trtcProperties.getEndpoint()); // 指定接入地域域名(默认就近接入)

            // 实例化一个client选项
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setSignMethod(ClientProfile.SIGN_TC3_256); // 指定签名算法(默认为TC3-HMAC-SHA256)
            clientProfile.setHttpProfile(httpProfile);
            clientProfile.setDebug(true);
            clientProfile.setLanguage(Language.ZH_CN);
            TrtcClient client = new TrtcClient(cred, "ap-shanghai", clientProfile);

            CreateCloudRecordingRequest request = new CreateCloudRecordingRequest();
            String userId = "recorder_" + roomId;
            request.setUserId(userId);
            Long sdkAppId = trtcProperties.getSdkAppId();
            TLSSigAPIv2 api = new TLSSigAPIv2(sdkAppId, trtcProperties.getSdkAppKey());
            String userSig = api.genUserSig(request.getUserId(), 180*86400);
            request.setUserSig(userSig);
            request.setSdkAppId(sdkAppId);
            request.setRoomId(roomId);
            RecordParams recordParams = new RecordParams();
            recordParams.setMaxIdleTime(60L);
            recordParams.setStreamType(0L);
            recordParams.setRecordMode(2L);
            request.setRecordParams(recordParams);
            MixTranscodeParams maxTranscodeParams = new MixTranscodeParams();
            VideoParams videoParams = new VideoParams();
            videoParams.setWidth(360L);
            videoParams.setHeight(640L);
            videoParams.setBitRate(500000L);
            videoParams.setFps(15L);
            videoParams.setGop(10L);
            maxTranscodeParams.setVideoParams(videoParams);
            request.setMixTranscodeParams(maxTranscodeParams);
            MixLayoutParams mixLayoutParams = new MixLayoutParams();
            mixLayoutParams.setMixLayoutMode(3L);
            request.setMixLayoutParams(mixLayoutParams);
            StorageParams storageParams = new StorageParams();
            CloudVod cloudVod = new CloudVod();
            TencentVod tencentVod = new TencentVod();
            tencentVod.setExpireTime(0L);
            cloudVod.setTencentVod(tencentVod);
            storageParams.setCloudVod(cloudVod);
            request.setStorageParams(storageParams);
            request.setRoomIdType(0L);
            CreateCloudRecordingResponse response = client.CreateCloudRecording(request);
            String taskId = response.getTaskId();
            String requestId = response.getRequestId();
            TrtcRecordTaskBo trtcRecordTask = new TrtcRecordTaskBo();
            trtcRecordTask.setRoomId(roomId);
            trtcRecordTask.setTaskId(taskId);
            trtcRecordTask.setUserId(userId);
            trtcRecordTask.setRequestId(requestId);
            trtcRecordTask.setSdkAppId(sdkAppId);
            trtcRecordTask.setRecordStartTime(new Date());
            trtcRecordTaskService.insertByBo(trtcRecordTask);
            System.out.println(response.toString());
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理房间销毁事件
     */
    private void handleRoomDestroyed(Map<String, Object> eventInfo) throws TencentCloudSDKException {
        Object roomIdObj = eventInfo.get("RoomId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        log.info("房间销毁: {}", roomId);
        Credential cred = new Credential(trtcProperties.getSecretId(), trtcProperties.getSecretKey());
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setReqMethod("GET"); // get请求(默认为post请求)
        httpProfile.setConnTimeout(30); // 请求连接超时时间，单位为秒(默认60秒)
        httpProfile.setWriteTimeout(30);  // 设置写入超时时间，单位为秒(默认0秒)
        httpProfile.setReadTimeout(30);  // 设置读取超时时间，单位为秒(默认0秒)
        httpProfile.setEndpoint(trtcProperties.getEndpoint()); // 指定接入地域域名(默认就近接入)
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setSignMethod(ClientProfile.SIGN_TC3_256); // 指定签名算法(默认为TC3-HMAC-SHA256)
        clientProfile.setHttpProfile(httpProfile);
        clientProfile.setDebug(true);
        clientProfile.setLanguage(Language.ZH_CN);
        TrtcClient client = new TrtcClient(cred, "ap-shanghai", clientProfile);
        DeleteCloudRecordingRequest request = new DeleteCloudRecordingRequest();
        Long sdkAppId = trtcProperties.getSdkAppId();
        request.setSdkAppId(sdkAppId);
        TrtcRecordTaskVo trtcRecordTaskVo = trtcRecordTaskService.selectTaskInfoByRoomId(roomId);
        String taskId = trtcRecordTaskVo.getTaskId();
        request.setTaskId(taskId);
        StopPublishCdnStreamRequest stopPublishCdnStreamRequest = new StopPublishCdnStreamRequest();
        stopPublishCdnStreamRequest.setSdkAppId(sdkAppId);
        stopPublishCdnStreamRequest.setTaskId(taskId);
        StopPublishCdnStreamResponse stopPublishCdnStreamResponse = client.StopPublishCdnStream(stopPublishCdnStreamRequest);
    }

    /**
     * 处理用户进入房间事件
     */
    private void handleUserEntered(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        Object userIdObj = eventInfo.get("UserId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String userId = userIdObj != null ? userIdObj.toString() : null;
        log.info("用户进入房间: roomId={}, userId={}", roomId, userId);
    }

    /**
     * 处理用户退出房间事件
     */
    private void handleUserExited(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        Object userIdObj = eventInfo.get("UserId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String userId = userIdObj != null ? userIdObj.toString() : null;
        log.info("用户退出房间: roomId={}, userId={}", roomId, userId);
    }
}
